﻿using System.Collections.Generic;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using Library.WebControls.SimplePaging;
using System.Web.UI;
using System;
using System.Text;

namespace Library.WebControls.SimpleGridView {
	internal sealed class SpDivGridView : HtmlGenericNaming {
		public SpDivGridView()
			: base("div") {
			Attributes["class"] = "spgrid";
			var dummy = new HtmlGenericControl("div");
			dummy.Style["width"] = "0px";
			dummy.Style["height"] = "0px";
			dummy.Style["overflow"] = "hidden";
			var checkBox = new HtmlInputCheckBox();
			checkBox.Attributes["onkeydown"] = "return true;";
			checkBox.Attributes["onkeyup"] = "return true;";
			checkBox.Attributes["onkeypress"] = "return true;";
			dummy.Controls.Add(checkBox);
			//Controls.Add(dummy);


			_divContentGrid = new HtmlGenericControl("div");
			_divContentGrid.Controls.Add(dummy);
			Controls.Add(_divContentGrid);
			_tableGrid = new Table { CellPadding = 0, CellSpacing = 0, Width = new Unit("100%") };
			_divContentGrid.Controls.Add(_tableGrid);
			_divPaging = new HtmlGenericControl("div");
			_divPaging.Attributes["class"] = "spgvDivPaging";

			Controls.Add(_divPaging);
			var divContainPaging = new HtmlGenericControl("div");
			divContainPaging.Attributes["class"] = "spgvDivContentPaging";
			_divPaging.Controls.Add(divContainPaging);
			_pagingControl = new SpPaging();
			//_pagingControl.CenterPagingControl.CreateCurrentPageText = CreateTextBox;
			//_pagingControl.CenterPagingControl.CreateNumberRowOfTextBox = CreateTextBox;
			divContainPaging.Controls.Add(_pagingControl);

			_divEditting = new DivHiddenEdit();
			Controls.Add(_divEditting);
			_childGridHolder = new PlaceHolder();
			Controls.Add(_childGridHolder);
		}

		private readonly DivHiddenEdit _divEditting;

		private readonly HtmlGenericControl _divContentGrid;
		internal HtmlGenericControl DivContentGrid {
			get { return _divContentGrid; }
		}
		internal HtmlGenericControl DivPaging {
			get { return _divPaging; }
		}
		private readonly HtmlGenericControl _divPaging;
		private readonly Table _tableGrid;
		internal Table TableGrid {
			get { return _tableGrid; }
		}

		private readonly PlaceHolder _childGridHolder;

		internal SpGridView ChildGrid {
			get {
				if (_childGridHolder.Controls.Count == 0)
					return null;
				return _childGridHolder.Controls[0] as SpGridView;
			}
			set {
				_childGridHolder.Controls.Clear();
				value.ParrentGrid = GridView;
				_childGridHolder.Controls.Add(value);
			}
		}


		private readonly SpPaging _pagingControl;
		public SpPaging PagingControl {
			get { return _pagingControl; }
		}

		private SpGridView _gridView;
		internal SpGridView GridView {
			get { return _gridView; }
			set {
				_gridView = value;
				_divEditting.Grid = value;
			}
		}
		public override string ClientID {
			get {
				if (GridView != null && !String.IsNullOrEmpty(GridView.ParrentKey)) {
					//return base.ClientID + ClientIDSeparator + GridView.ParrentRowIndex;
					return base.ClientID + ClientIDSeparator + GridView.ParrentKey;
				}

				return base.ClientID;
			}
		}

		public override string ID {
			get {

				if (GridView != null && !String.IsNullOrEmpty(GridView.ParrentKey)) {
					return base.ID + ClientIDSeparator + GridView.ParrentKey;
					//return base.ID + GridView.ParrentKey;
				}

				return base.ID;
			}
			set {
				base.ID = value;
			}
		}

		public string ClientSendRequestId {
			get { return base.ClientID; }
		}

		internal bool ClientVisible {
			get { return Style[HtmlTextWriterStyle.Display] != "none"; }
			set {
				if (value) {
					Style.Remove(HtmlTextWriterStyle.Display);
				} else {
					Style[HtmlTextWriterStyle.Display] = "none";
				}
			}
		}
		internal DivHiddenEdit DivEditting {
			get {
				EnsureChildControls();
				return _divEditting;
			}
		}

		//private void BindingEditControl() {
		//  if (GridView.HasChildGrid) {
		//    _divEditting.Controls.Add(new HtmlGenericControl("span"));
		//  }
		//  foreach (var column in GridView.Columns) {
		//    _divEditting.AddEditControl(column);
		//  }
		//}
		internal void RenderMeWithoutChildGrid(HtmlTextWriter writer) {

			_childGridHolder.Visible = false;
			_divPaging.Visible = _pagingControl.Visible;
			Attributes["onkeydown"] = "return " + GridView.ClientName + ".Call(6, event)";
			Render(writer);
		}


		internal void RenderChildGridWithoutMe(HtmlTextWriter writer) {
			_divPaging.Visible = _pagingControl.Visible;
			_childGridHolder.RenderControl(writer);
			if (_divEditting.Visible) _divEditting.RenderControl(writer);
		}

		internal void RenderBodyWithoutChildGrid(HtmlTextWriter writer) {
			_divPaging.Visible = _pagingControl.Visible;
			_divContentGrid.RenderControl(writer);
			_divPaging.RenderControl(writer);
		}


		//private TextBox CreateTextBox() {
		//  return new GridViewPagingControlText(this);
		//}

		//private class GridViewPagingControlText : TextBox {
		//  private readonly SpDivGridView _div;
		//  public GridViewPagingControlText(SpDivGridView divGridView) {
		//    _div = divGridView;
		//  }
		//  public override string ClientID {
		//    get { return _div.ClientID + ClientIDSeparator + ID; }
		//  }
		//}

		internal class DivHiddenEdit : HtmlGenericControl {
			private readonly SpGvColumnCollection _column;

			public SpGridView Grid { private get; set; }
			private readonly List<KeyValuePair<BaseControl, SpGvBaseColumn>> _editControls;

			public DivHiddenEdit()
				: base("span") {
				Style.Add(HtmlTextWriterStyle.Display, "none");
				_editControls = new List<KeyValuePair<BaseControl, SpGvBaseColumn>>();
				_column = new Columns(this);
			}

			internal SpGvColumnCollection Column { get { return _column; } }


			private void AddEditControl(SpGvBaseColumn control) {
				BaseControl edit = null;
				if (control.EditState != EditState.None) {
					edit = control.CreateClientEditControl();
					edit.ID = "editControl_" + Controls.Count;
				}

				var div = new DivBaseControl(edit, control);
				_editControls.Add(new KeyValuePair<BaseControl, SpGvBaseColumn>(edit, control));
				Controls.Add(div);

			}
			private void ClearEditControl() {
				_editControls.Clear();
				Controls.Clear();
			}
			private void RemoveEditControl(SpGvBaseColumn control) {
				for (int i = 0; i < Controls.Count; i++) {
					var ctr = (DivBaseControl)Controls[i];
					if (ReferenceEquals(ctr.Column, control)) {
						Controls.RemoveAt(i);
						break;
					}
				}

				for (int i = 0; i < _editControls.Count; i++) {
					var kv = _editControls[i];
					if (ReferenceEquals(kv.Value, control)) {
						_editControls.RemoveAt(i);
						break;
					}
				}
			}

			private sealed class DivBaseControl : HtmlGenericControl {
				public readonly SpGvBaseColumn Column;
				private readonly BaseControl _control;
				public DivBaseControl(BaseControl control, SpGvBaseColumn column)
					: base("div") {
					_control = control;
					Column = column;
					if (control != null)
						Controls.Add(control);
					//else {
					//  Controls.Add(new HtmlGenericControl("span"));
					//}
				}

				public override bool Visible {
					get {
						if (_control != null)
							return _control.Visible;
						return base.Visible;
					}
					set {
						if (_control != null)
							_control.Visible = value;
						else base.Visible = value;
					}
				}
			}

			protected override void Render(HtmlTextWriter writer) {
				if (Grid.HasChildGrid) {
					Controls.AddAt(0, new HtmlGenericControl("span"));
				}
				Controls.Add(new ScriptControl(_editControls, Grid));
				base.Render(writer);
			}

			private class ScriptControl : Control {
				private readonly SpGridView _grid;
				private readonly List<KeyValuePair<BaseControl, SpGvBaseColumn>> _editControls;
				public ScriptControl(List<KeyValuePair<BaseControl, SpGvBaseColumn>> editControl, SpGridView grid) {
					_editControls = editControl;
					_grid = grid;

				}
				protected override void Render(HtmlTextWriter writer) {

					var columnInitBuilder = new StringBuilder();
					columnInitBuilder.Append("[");
					if (_grid.HasChildGrid) columnInitBuilder.Append("{},");
					foreach (var editControl in _editControls) {
						if (!editControl.Value.Visible) continue;
						if (String.IsNullOrEmpty(editControl.Value.Name)) {
							throw new Exception("Inline edit mode, all visible columns must has unique conlumn name and not null");
						}
						if (editControl.Key == null) {
							columnInitBuilder.Append("{},");
						} else {
							columnInitBuilder.Append("{Ctr:");
							columnInitBuilder.Append(editControl.Key.ClientName);
							columnInitBuilder.Append(",Name:'");
							columnInitBuilder.Append(editControl.Value.Name);
							columnInitBuilder.Append("',Type:");
							columnInitBuilder.Append((Int32)editControl.Value.ColumnType);
							columnInitBuilder.Append(",Edit:");
							columnInitBuilder.Append((Int32)editControl.Value.EditValueMode);
							columnInitBuilder.Append(",State:");
							columnInitBuilder.Append((Int32)editControl.Value.EditState);
							columnInitBuilder.Append("},");
						}
					}
					if (columnInitBuilder.Length > 1) {
						columnInitBuilder.Remove(columnInitBuilder.Length - 1, 1);
					}
					columnInitBuilder.Append("]");
					if (columnInitBuilder.Length > 2) {
						writer.Write("<script language='javascript' type='text/javascript'>");
						writer.Write("{0}.InitColumns({1});", _grid.ClientName, columnInitBuilder);
						writer.Write("</script>");
					}
				}
			}

			private class Columns : SpGvColumnCollection {

				private readonly DivHiddenEdit _edit;
				public Columns(DivHiddenEdit edit) {
					_edit = edit;
				}
				public override void Add(SpGvBaseColumn item) {
					base.Add(item);
					_edit.AddEditControl(item);
				}

				public override void Insert(int index, SpGvBaseColumn item) {
					base.Insert(index, item);
					_edit.AddEditControl(item);
				}

				public override bool Remove(SpGvBaseColumn item) {
					var result = base.Remove(item);
					if (result) {
						_edit.RemoveEditControl(item);
					}

					return result;
				}

				public override void Clear() {
					base.Clear();
					_edit.ClearEditControl();
				}

				public override void RemoveAt(int index) {
					var item = this[index];
					base.RemoveAt(index);
					_edit.RemoveEditControl(item);
				}


			}
		}
	}
}
